#pragma once 
#include <iostream>
#include <unordered_map>
#include <sys/epoll.h>
#include <unistd.h>
#include <string>

namespace my_epoll
{

 
  class reactor;
  class EventItem;

  typedef int(*callback_t)(EventItem*);

  class EventItem
  {
    public:
      int sock;
      reactor *R;

      callback_t recv_handler;
      callback_t send_handler;
      callback_t error_handler;

      std::string inbuffer;
      std::string outbuffer;
    public:
      EventItem():sock(0),R(nullptr),recv_handler(nullptr),send_handler(nullptr),error_handler(nullptr)
    {}
      ~EventItem()
      {}

      void ManagerCallBack(callback_t _recv,callback_t _send,callback_t _error)
      {
        recv_handler=_recv;
        send_handler=_send;
        error_handler=_error;
      }
  };
  class reactor
  {
    private:
      int epfd;
      std::unordered_map<int,EventItem> event_items;

    public:
      reactor():epfd(-1)
    {}
      ~reactor()
      {
        if(epfd>=0)
          close(epfd);
      }
     void Isitreactor()
     {
       epfd=epoll_create(256);
       if(epfd<0)
       {
         std::cerr<<" epoll_create error"<<std::endl;
         exit(4);
       }
       std::cout<<"dubge epfd"<<epfd<<std::endl;
     }

     void AddEvent(int sock,uint32_t event,const EventItem &item)
     {
       struct epoll_event ev;
       ev.data.fd=sock;
       ev.events=0;
       ev.events|=event;
       if(epoll_ctl(epfd,EPOLL_CTL_ADD,sock,&ev)<0)
       {
         std::cerr<<"epoll 添加失败"<<sock<<std::endl;
       }else{
         event_items.insert({sock,item});
       }
       std::cout<<"debug epoll添加成功："<<sock<<std::endl;
     }

     void Delevent(int sock)
     {
       if(epoll_ctl(epfd,EPOLL_CTL_DEL,sock,nullptr)<0)
       {
         std::cerr<<"epoll模型删除失败： "<<sock<<std::endl;
       }
       event_items.erase(sock); 
     }
     
     void EnableReadWrite(int sock,bool read,bool write)
     {
       struct epoll_event evt;
       evt.data.fd=sock;
       evt.events= (read?EPOLLIN:0)|(write?EPOLLOUT:0)|EPOLLET;
       if(epoll_ctl(epfd,EPOLL_CTL_MOD,sock,&evt)<0)
       {
         std::cerr<<"epoll_ctl 修改失败："<<sock<<std::endl;
       }
     }
     void Dispatcher(int timeout)
     {
       int q=0;
       struct epoll_event revs[256];
       int num=epoll_wait(epfd,revs,256,timeout);
       for(int i=0;i<num;i++)
       {
         int sock=revs[i].data.fd;
         uint32_t mask=revs[i].events;

        /* if((revs[i].events& EPOLLERR)||(revs[i].events&EPOLLHUP))
         mask|=(EPOLLIN|EPOLLOUT);*/

         if((revs[i].events& EPOLLERR)||(revs[i].events&EPOLLHUP))
           event_items[sock].error_handler(&event_items[sock]);
         std::cout<<q<<"er"<<std::endl;
         if(revs[i].events&EPOLLIN)
           if(event_items[sock].recv_handler)
             event_items[sock].recv_handler(&event_items[sock]);
         std::cout<<q<<"r"<<std::endl;
         if(revs[i].events&EPOLLOUT)
           if(event_items[sock].send_handler)
             event_items[sock].send_handler(&event_items[sock]);

         std::cout<<q<<"w"<<std::endl;
         q++;
        }
     }

  };
}
